#include "CbintreeCode.h"

//using namespace Ogre;
using namespace std;

int CbintreeCode::DirX[8]={1,-1,1,0,-1,1,-1,0};
int CbintreeCode::DirY[8]={-1,0,1,-1,1,0,-1,1};

CbintreeCode::CbintreeCode(void)
{
}

CbintreeCode::CbintreeCode( std::string code ):mCode(code)
{
	
}
CbintreeCode::~CbintreeCode(void)
{
}

void CbintreeCode::GetPos( float &x0,float &y0,float &x1,float &y1,float &x2,float &y2 )
{
	float x,y;
	Direction dirt;
	if (mCode[0]=='0')
	{
		x=0.0f;
		y=1.0f;
		dirt=SOUTH_EAST;
	}
	else
	{
		x=1.0f;
		y=0.0f;
		dirt=NORTH_WEST;
	}
	float step=0.5f;
	size_t i=1;
	for (;i<mCode.length();++i)
	{
		x+=DirX[dirt]*step;
		y+=DirY[dirt]*step;
		if (i%2==0)
		{
			step*=0.5f;
		}
		if (mCode[i]=='0'){
			dirt=Direction((dirt+1)%8);
		}
		else{
			dirt=Direction(((int)dirt-1+8)%8);
		}
		
	}

	x0=x;
	y0=y;

	x1=(DirX[dirt]+DirY[dirt])*step+x;
	y1=(-DirX[dirt]+DirY[dirt])*step+y;

	x2=(DirX[dirt]-DirY[dirt])*step+x;
	y2=(DirX[dirt]+DirY[dirt])*step+y;

}

void CbintreeCode::GetPos( float &x0,float &y0 )
{
	float x,y;
	Direction dirt;
	if (mCode[0]=='0')
	{
		x=0.0f;
		y=1.0f;
		dirt=SOUTH_EAST;
	}
	else
	{
		x=1.0f;
		y=0.0f;
		dirt=NORTH_WEST;
	}
	float step=0.5f;
	size_t i=1;
	for (;i<mCode.length();++i)
	{
		x+=DirX[dirt]*step;
		y+=DirY[dirt]*step;
		if (i%2==0)
		{
			step*=0.5f;
		}
		if (mCode[i]=='0'){
			dirt=Direction((dirt+1)%8);
		}
		else{
			dirt=Direction(((int)dirt-1+8)%8);
		}

	}

	x0=x;
	y0=y;
}
std::string CbintreeCode::GetBaseCode( const std::string &code )
{
	string ret;
	if (code.length()==1)
	{
		if (code[code.length()-1]=='0')
		{
			return "1";
		}
		else
		{
			return "0";
		}
	}
	if (code[code.length()-1]=='0')
	{
		ret=GetRightChildCode(GetLeftCode(code.substr(0,code.length()-1)));
	}
	else{
		ret=GetLeftChildCode(GetRightCode(code.substr(0,code.length()-1)));
	}
	return ret;
}

std::string CbintreeCode::GetLeftCode(const std::string &code )
{
	if (code.length()<=1)
	{
		return "";
	}
	string ret;
	if (code[code.length()-1]=='0')
	{
		ret=code.substr(0,code.length()-1)+"1";
	}
	else
	{
		ret=GetLeftChildCode(GetBaseCode(code.substr(0,code.length()-1)));
	}
	return ret;

}

std::string CbintreeCode::GetRightCode(const std::string &code )
{
	if (code.length()<=1)
	{
		return "";
	}
	string ret;
	if (code[code.length()-1]=='1')
	{
		ret=code.substr(0,code.length()-1)+"0";
	}
	else
	{
		ret=GetRightChildCode(GetBaseCode(code.substr(0,code.length()-1)));
	}
	return ret;

}

std::string CbintreeCode::GetLeftChildCode( const std::string &code )
{
	return code.length()==0?"":code+"0";
}

std::string CbintreeCode::GetRightChildCode( const std::string &code )
{
	return code.length()==0?"":code+"1";
}
//base on 0 index
 unsigned int CbintreeCode::GetHashNum( const std::string &code )
{
//	OgreProfile("GetHashNum");
//	unsigned int ret= (code.length()==1)?0:(((1<<(code.length()-1))-1)<<1);
	int length=code.length();
	unsigned int ret= (((1<<(length-1))-1)<<1);
	for (int i=length-1;i>=0;--i)
	{
		ret+=(code[i]=='0')?0:(1<<(length-1-i));
	}
	return ret+1;
}

std::string CbintreeCode::GetParentCode( const std::string &code )
{
	return code.length()<=1?"":code.substr(0,code.length()-1);
}

std::string CbintreeCode::GetBrotherCode( const std::string &code )
{
	if (code.length()>1){
		string ret=code;
		ret[ret.length()-1]=abs(ret[ret.length()-1]-'0'-1)+'0';
		return ret;
	}
	else{
		return "";
	}
		
}
//unsigned int CbintreeCode::BinStrToInt( const std::string &code )
//{
//	unsigned int ret=0;
//	unsigned int j=1;
//	for (size_t i=code.length()-1;i>=0;--i)
//	{
//		ret+=(code[i]=='0')?0:(j);
//		j=j<<1;
//	}
//	return ret;
//
//}